{"componentChunkName":"component---src-templates-post-tsx","path":"/javascript-study_3/","result":{"data":{"markdownRemark":{"html":"<p>표현식 (expression)은 자바스크립트 인터프리터가 값으로 평가하는(evaluate) 자바스크립트 구문이다. 예를 들어 프로그램에 포함된 임의의 상수는 표현식의 아주 간단한 형태다. 변수 이름 또한 간단한 표현식으로, 변수에 할당된 임의의 값으로 평가된다. 이처럼 간단한 표현식들을 사용해 복잡한 표현식도 만들 수 있다. 예를 들어 배열 접근 표현식은 열린 대괄호([) 와 숫자로 평가되는 표현식, 닫힌 대괄호(])가 결합된 하나의 표현식이다. 이렇게 결합된 복잡 표현식은 배열의 특정 위치에 저장된 값으로 평가된다. 이와 유사하게, 함수 호출 표현식은 함수 객체와 인자로 사용되는 하나 이상의 표현식들이 결합해 하나의 복합 표현식이 된다.</p>\n<p>복합 표현식을 만드는 가장 쉬운 방법은 연산자(operator)를 사용하는 것이다. 연산자는 피연산자의 값들을(보통 두 개) 어떻게든 결합해 새로운 값을 만들어 낸다. 곱셈 연산자 _가 그 간단한 사례다. 표현식 x _ y는 표현식 x와 y 값의 곱으로 평가된다. 간단히 설명하기 위해, 연산자는 '값으로 평가된다'는 표현 대신, '값을 반환한다'는 표현을 쓰기도 한다.</p>\n<p>이번 장에서는 자바스크립트에서 사용하는 모든 연산자뿐 아니라, 배열 참조나 함수 호출처럼 연산자를 사용하지 않는 표현식도 다룬다. 만약 독자 여러분이 C 스타일 문법을 사용하는 다른 프로그래밍 언어를 배운 적이 있다면, 자바스크립트의 표현식과 연산자 문법이 한결 친숙할 것이기에 이 장을 좀 더 빠르게 살펴볼 수 있을 것이다.</p>\n<p>4.1 기본 표현식\n가장 간단한 형태의 표현식은 '기본 표현식(primary expression)'으로, 다른 표현식을 포함하지 않은 독립적 표현식이다. 자바스크립트에서 기본 표현식은 상수나 리터럴 값, 특정 키워드들 그리고 변수 참조를 말한다.\n리터럴은 상수 값으로 프로그램에 직접 포함된다. 예를 들어 다음과 같다.</p>\n<p>1.234 // 숫자 리터럴\n\"hello\" // 문자열 리터럴\n/pattern/ // 정규 표현식 리터럴</p>\n<p>숫자 리터럴을 작성하는 자바스크립트 문법은 3.1절에서, 문자열 리터럴은 3.2절에서 다뤘다. 정규 표현식 리터럴 문법도 3.2.4에서 간단히 소개했지만 10장에서 좀 더 자세히 다룬다.\n자바스크립트의 예약어 중에는 기본 표현식이 몇 개 있다.</p>\n<p>true // 불리언 true 값으로 평가된다.\nfalse // 불리언 false 값으로 평가된다.\nnull // null 값으로 평가된다.\nthis // '현재' 객체로 평가된다.</p>\n<p>3.3절과 3.4절에서 true, false, null에 대해 살펴봤다. 다른 키워드와는 달리 this는 상수가 아니고 프로그램 안에서 위치에 따라 각기 다른 값으로 평가된다. this 키워드는 객체 지향 프로그래밍에서 주로 사용된다. 메서드의 본문 안에서 this는 메서드를 호출한 객체로 평가된다. 4.5절과 8장(특히 8.2.2), 9장에서 this에 대해 좀 더 상세히 다루겠다. 마지막으로 세 번째 기본 표현식은 변수를 있는 그대로 참조하는 형태다.</p>\n<p>i // 변수 i의 값으로 평가된다.\nsum // 변수 sum의 값으로 평가된다.\nundefined // undefined는 전역 변수로 null처럼 키워드가 아니다.</p>\n<p>자바스크립트에서는 프로그램 안에 존재하는 각 식별자들을 일단 변수라고 가정하고 값을 살펴본다. 만약 해당 식별자를 이름으로 하는 변수가 없다면, 해당 표현식은 undefined 값으로 평가된다. 하지만 ECMAScript 5의 엄격 모드 (strict mode)에서는 존재하지 않는 변수를 평가하려고 하면 ReferenceError 예외가 발생한다.</p>\n<p>4.2 객체와 배열의 초기화 표현식</p>\n<p>객체와 배열 초기화 표현식(initializer)은 말 그대로 새로 생성된 객체나 배열을 값으로 하는 표현식이다. 이들 초기화 표현식은 종종 '객체 리터럴'과 '배열 리터럴' 이라고 한다. 하지만 일반 리터럴과는 달리, 이들은 기본 표현식이 아니다. 이들 리터럴은 프로퍼티와 원소의 값을 지정하는 수많은 하위 표현식을 포함할수 있기 때문이다. 배열 초기화 문법은 상대적으로 간단하니, 이 부분부터 살펴보자.\n배열 초기화 표현식은 대괄호 안에 담긴 쉼표로 구분된 표현식 리스트다. 배열 초기화 표현식의 값은 새로 생성된 배열이다. 이렇게 생성된 배열의 원소들은 각각 쉼표로 구분된 표현식의 값들로 초기화된다.</p>\n<p>[] // 빈 배열: 대괄호 안에 표현식이 없으면 원소가 없음을 말\n한다.\n[1+2, 3+4] // 두 개의 원소를 가진 배열. 첫 번째는 3, 두 번째는 7이다.</p>\n<p>배열 초기화 표현식에 사용되는 원소 표현식으로는 또 다른 배열 초기화 표현식을 사용할 수도 있다. 다시 말해, 원소 표현식 자체가 배열이라면 중첩 배열을 만들 수도 있다는 의미다.</p>\n<p>var matrix = [[1,2,3], [4,5,6], [7,8,9]];</p>\n<p>배열 초기화 표현식에 사용되는 원소 표현식은 매번 배열이 초기화될 떄마다 평가된다. 이는 배열 초기화 표현식이 평가될 때마다 원소의 값이 달라질 수 있음을 뜻한다.\n배열 리터럴에서 쉼표 사이의 값을 생략함으로써 원소의 값을 정의하지 않을수 있다. 예를 들어, 다음 배열은 세 개의 정의되지 않은 원소를 포함해 총 다섯개 원소를 갖고 있다.</p>\n<p>var sparseArray = [1,,,,,,5];</p>\n<p>배열 초기화 표현식의 마지막 원소 표현식 다음에 쉼표가 올 수는 있지만, 그렇다고 해서 값이 정의되지 않은 원소가 만들어지지는 않는다. 객체 초기화 표현식은 배열 초기화 표현식과 유사하다. 하지만 대괄호가 아닌 중괄호가 사용되고, 각 하위 표현식 앞에는 프로퍼티 이름과 콜론(:)이 붙는다.</p>\n<p>var p = { x : 2.3, y : -1.2 }; // 두 개의 프로퍼티를 가진 객체\nvar q = {}; // 프로퍼티가 없는 빈 객체\nq.x = 2.3; q.y = -1.2; // 객체 q와 p는 같은 프로퍼티를 갖는다.</p>\n<p>객체 리터럴은 중첩될 수 있다. 예를 통해 살펴보자.</p>\n<p>var rectangle = { upperLeft : { x : 2, y : 2 },\nlowerRight : { x : 4, y : 5 } } ;</p>\n<p>객체 초기화에 사용한 표현식은 객체가 초기화 될 떄마다 매번 평가되기 때문에 일정한 값을 갖지 않는다. 그 자체로 임의의 자바스크립트 표현식이기 때문이다. 객체 리터럴에서의 프로퍼티 이름으로는 식별자 대신 문자열을 사용할 수도 있다(이는 예약어나, 식별자로는 적합하지 않은 이름을 프로퍼티 이름으로 사용 하고 싶을 때 유용하다).</p>\n<p>var side = 1;\nvar square = { \"upperLeft\" : { x : p.x, y : p.y },\n\"lowerRight\" : { x : p.x + side, y : p.y + side } } ;</p>\n<p>객체와 배열 초기화 표현식은 6장과 7장에서 좀 더 상세히 다룬다.</p>\n<p>4.3 함수 정의 표현식</p>\n<p>함수 정의 표현식 ( function definition expression)은 함수를 정의하고, 함수 정의 표현식의 값은 새로 정의된 함수다. 다시 말해, 함수 정의 표현식은 '함수 리터럴'이라 할 수 있다. 이는 객체 초기화 표현식을 '객체 리터럴' 이라고 말하는것과 같다. 함수 정의 표현식은 일반적으로 function 키워드와 중괄호로 둘러싸인 쉼표로 구분된 식별자(매개변수 이름) 목록, 중괄호로 둘러싸인 자바스크립트 코드(함수 몸체)로 이루어진다. 예를 들어, 다음의 코드를 살펴보자.</p>\n<p>// 이 함수는 전달된 값을 제곱하여 반환한다.\nvar square = function(x) { return x * x; }</p>\n<p>함수 정의 표현식은 함수 이름을 포함할 수 있다. 또한 함수는 함수 정의 표현식 대신에 함수 구문(function statement)을 사용해 정의할 수 있다. 함수 정의에 대해서는 8장에서 좀 더 자세히 알아볼 것이다.</p>\n<p>4.4 프로퍼티 접근 표현식</p>\n<p>프로퍼티 접근 표현식은 객체의 프로퍼티나 배열의 원소 값으로 평가된다. 자바스크립트에서는 두 가지 문법으로 프로퍼티에 접근할 수 있다.</p>\n<p>표현식 . 식별자\n표현식 [ 표현식 ]</p>\n<p>첫 번째 프로퍼티 접근 방법은 표현식에 식별자를 점(.)으로 연결한 표현식이다. 여기서 표현식은 객체를 말하고, 식별자는 앞에서 지정한 객체에서 찾을 프로퍼티의 이름을 의미한다. 프로퍼티 접근의 두 번째 방법은 객체나 배열이 되는 첫 번째 표현식 다음에 열린 대괄호와 두 번째 표현식 그리고 닫힌 대괄호를 사용하는 것이다. 여기서 사용한 두 번째 표현식은 객체의 특정 프로퍼티 이름이나 배열 내 원소의 인덱스 값이 될 수 있다. 다음 예제를 통해 자세히 살펴보자.</p>\n<p>var o = { x : 1, y : { z : 3 } }; // 간단한 객체 리터럴 예제\nvar a = [o,4, [5,6]]; // 객체를 포함한 간단한 배열 리터럴 예제\no.x // 1: 표현식 o의 프로퍼티 x의 값\no.y.z // 3: 표현식 o.y의 프로퍼티 z의 값\no[\"x\"] // 1: 객체 o의 프로퍼티 x의 값\na[1] // 4: 표현식 a의 인덱스 1 위치에 있는 원소 값\na[2][\"1\"] // 6: 표현식 a[2]의 인덱스 1 위치에 있는 원소 값\na[0].x // 1: 표현식 a[0]의 프로퍼티 x의 값</p>\n<p>두 프로퍼티 접근 표현식 모두 점(.)이나 대괄호 ([) 왼쪽 표현식이 먼저 평가된다. 만약 평가된 값이 null 이나 undefined이면 이들 값은 프로퍼티를 갖지 않기 때문에 표현식은 TypeError 예외를 발생시킨다. 만약 값이 객체(또는 배열)가 아니면 객체로 변환된다(3.6절 참고). 만약 객체 표현식 다음에 점(.)과 식별자가 올 경우에는 식별자를 이름으로 갖는 프로퍼티의 값을 찾게 되고, 이 값이 전체 표현식의 값이 된다.\n만약 객체 표현식 다음에 두 번째 표현식이 담긴 대괄호가 올 경우에는 두 번째 표현식이 평가되고, 이 값이 문자열로 변환된다. 전체 표현식의 값은 앞에서 변환된 문자열을 이름으로 갖는 프로퍼티의 값이 된다.\n두 경우 모두, 객체에 해당 프로퍼티가 존재하지 않으면, 프로퍼티 접근 표현식의 값은 undefined가 된다.</p>\n<p>'. 식별자' 문법이 두 방법 중 좀 더 간단하다. 하지만 접근하려는 프로퍼티 이름이 '합법적' 식별자일 때만 사용할 수 있고, 프로그램을 작성할 때 그 식별자를 미리 알고 있어야 한다. 만약 프로퍼티 이름이 예약어이거나, 구두점 문자나 공백을 포함하고 있거나, 숫자(배열의 경우)일 때는 반드시 대괄호를 사용해야 한다. 대괄호는 프로퍼티 이름이 고정되어 있지 않고, 그 이름 자체가 어떤 연산의 결과인 경우에도 사용할 수 있다 ( 6.2.1에서 다룬 예제 참고). 객체와 객체 프로퍼티에 대해서는 6장에서, 배열과 배열의 원소에 대해서는 7장에서 자세히 다룬다.</p>\n<p>4.5 호출 표현식</p>\n<p>호출 표현식(invocation expression)은 자바스크립트에서 함수나 메서드를 호출하는(또는 실행시키는) 문법이고, 호출될 함수를 가리키는 함수 표현식으로 시작한다. 그 뒤에는 여는 괄호로 시작해 쉼표(,)로 구분된 여러 개의 호출 인자 목록이 올 수 있고, 닫는 괄호로 끝난다. 예를 들면, 다음과 같다.</p>\n<p>f(0) // f는 함수 표현식이다. 여기서 '0'은 인자 표현식이다.\nMath.max(x,y,z) // Math.max는 함수고, x,y,z가 호출 인자다.\na.sort() // a.sort는 함수고, 호출 인자가 없다.</p>\n<p>호출 표현식이 평가될 때 함수 표현식이 가장 먼저 평가되고, 그 후에 호출 인자 표현식이 순서대로 인자 값으로 평가된다. 함수 표현식의 값이 호출할 수 있는 객체가 아닐 경우는 TypeError 예외가 발생하게 된다(모든 함수는 호출 가능하다. 함수가 아닌 호스트 객체도 호출이 가능한 경우가 있다. 그 차이점은 8.7.7에서 살펴보기로 한다). 인자 값이 평가된 다음에는 함수 선언 시 지정했던 인자 이름에 인자 값이 차례로 할당되고, 마지막으로 함수의 본문이 실행된다. 값을 반환하기 위해 return문을 사용하면, 그 값이 결국 호출 표현식의 값이 된다. 함수가 값을 반환하지 않는다면, 함수 표현식의 값은 undefined가 된다. 함수 호출과 관련한 좀 더 자세한 사항은 8장에서 살펴보기로 하자.</p>\n<p>모든 호출 표현식은 한 쌍의 괄호 () 와, 괄호 앞에 오는 표현식으로 이뤄진다. 만약 그 표현식이 프로퍼티 접근 표현식이면, 호출 표현식은 메서드 호출이 된다. 메서드가 호출되면 함수의 몸체가 실행되는 동안 프로퍼티 접근 표현식이 가리키는 객체나 배열이 모두 this의 값이 된다. 이는 함수(객체 지향에서는 '메서드'로 알려진)가 자신이 속한 객체를 대상으로 동작하게 하므로 객체 지향적으로 프로그램을 작성할 수 있게 한다. 이와 관련해서는 9장에서 좀 더 자세히 살펴보겠다.</p>\n<p>메서드 호출이 아닌 호출 표현식은 보통 전역 객체를 this 키워드의 값으로 사용한다. 하지만 ECMAScript 5에서는 메서드 호출이 아닌 호출 표현식을 '엄격 모드'에서 사용할 경우, 전역 객체 대신 undefined가 this의 값이 된다. 5.7.3에서 '엄격 모드'에 대해 자세히 살펴보겠다.</p>\n<p>4.6 객체 생성 표현식</p>\n<p>객체 생성 표현식(object creation expression)은 새 객체를 생성하고, 생성자라고 부르는 함수를 호출해 객체에 속한 프로퍼티들을 초기화한다. 객체 생성 표현식은 new 키워드가 앞에 붙는다는 점을 제외하면 호출 표현식과 유사하다.</p>\n<p>new Object()\nnew Point(2,3)</p>\n<p>객체의 생성자 함수를 전달인자 없이 호출할 때, 다음과 같이 괄호를 생략할 수 있다.</p>\n<p>new Object\nnew Darte</p>\n<p>객체 생성 표현식이 평가될 때, 자바스크립트 인터프리터는 먼저 새로운 빈 객체를 생성하는데, 이때 생성된 객체는 객체 초기자 {}에 의해 생성되는 객체와 동일하다. 다음으로, 주어진 인자들과 함께 생성자를 호출하는데, 이때 방금 생성된 새 객체를 this 키워드의 값으로 설정하여 전달한다. 생성자 함수는 이 this 키워드를 사용해 새로 생성된 객체의 프로퍼티들을 초기화한다.</p>\n<p>일반적으로 생성자로 사용되는 함수는 값을 반환하지 않는다. 객체 생성 표현식의 값은 새롭게 생성되고 초기화된 객체다. 생성자가 특정 객체 값을 반환할 경우, 이 값이 객체 생성 표현식의 값이 되고 생성자를 통해 새로 생성된 객체는 버려진다. 생성자 함수에 대한 좀 더 자세한 설명은 9장에서 다룬다.</p>\n<p>4.7 연산자 개요</p>\n<p>연산자는 수식 표현식, 비교 표현식, 논리 표현식, 할당 표현식 등 자바스크립트에서 다양하게 쓰인다. 표 4-1에서는 각 연산자가 하는 역할을 요약하고 우선순위순으로 나열하였다.\n대부분의 연산자가 +와 = 같은 부호로 표현되지만, 일부는 delete와 instanceof와 같이 키워드로 표현한다. 키워드 연산자들도 문장 부호 연산자들과 마찬가지로 정규 연산자인데, 문장 부호 연산자와 비교해 덜 간결한 형태로 표현된 것뿐이다.</p>\n<p>표 4-1은 연산자를 연산 우선순위로 정렬했다. 목록에 나열된 연산자 중에서 먼저 나온 연산자가 나중 나온 연산자보다 연산 우선순위가 높다. 이처럼, 연산자는 우선순위 단계에 따라 선으로 구분되어 있다. 표에서 '결합 방향' 열은 연산자 결합 방향을 나타내는데 , L은 '왼쪽에서 오른쪽으로'를 의미하고 R은 '오른쪽에서 왼쪽으로'를 뜻한다. 그리고 '피연산자 개수' 열은 해당 연산자가 갖는 피연산자의 개수를 뜻한다. '피연산자 타입' 열은 연산자가 사용할 피연산자들의 타입을, '반환' 열은 연산자가 평가된 후 반환하는 객체 타입을 말한다. 이어지는 절에서는 표 4-1에 나와 있는 연산자들의 연산 우선순위와 결합 방향 그리고 피연산자 타입에 대해 살펴볼 것이다. 또한 연산자 자체에 대해서도 살펴보겠다.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">                       표 4-1 자바스크립트 연산자</code></pre></div>\n<p>4.7.1 피 연산자 개수</p>\n<p>연산자에 필요한 피연산자의 개수에 따라 연산자들을 분류할 수 있다. 곱셈 연산자 * 처럼 자바스크립트 연산자 대부분은 2항 연산자(binary operator)다. 2항 연산자는 두 개의 표현식을 조합하여 하나의 복합 표현식으로 만들어낸다. 자바스크립트는 단항 연산자(unary operator)도 지원한다. 이런 연산자는 하나의 표현식을 좀 더 복잡한 단일 표현식으로 바꾼다. 가령 -x와 같은 표현식에서 - 연산자는 피연산자 x의 부호를 전환한다. 마지막으로 자바스크립트는 3항 연산자 (ternary operator )도 하나 지원하는데, 바로 조건부 연산자인 ?: 이다. 이는 세 표현식들의 값을 조합해 하나의 표현식으로 만들어 낸다.</p>\n<p>4.7.2 피연산자와 반환 타입</p>\n<p>일부 연산자는 값의 타입과 무관하게 동작하지만 대부분의 경우에는 피연산자 타입이 정해져 있다. 그리고 연산자들은 대체로 특정 타입의 값을 반환(또는 평가)한다. 표 4-1의 '피연산자 타입' 열은 연산자별로 피연산자 타입과 평가 후 반환되는 타입을 보여준다.\n자바스크립트는 필요할 떄마다 피연산자 타입을 변환한다(3.8절 참고). 곱셈 연산자 _는 두 개의 숫자 타입을 피연산자로 갖지만, 표현식 '3' _ '5'는 자바스크립트가 두 개의 피연산자를 숫자로 바꾸기 때문에 특별히 문제가 되지 않는다.</p>\n<p>이 표현식의 값은 문자열 '15'가 아니라 숫자 15다. 또한, 자바스크립트에서 모든 값은 참이나 거짓으로 평가된다는 점을 기억하자. 따라서 불리언 값을 피연산자로 갖는 연산자는 어떤 타입의 피연산자와도 문제없이 동작한다.</p>\n<p>일부 연산자들은 피연산자의 타입에 따라 다르게 작동한다. 대표적으로 + 연산자는 피연산자가 숫자 타입이면 덧셈을 하지만, 문자열 타입이면 문자열을 이어붙인다. 이와 유사하게, &#x3C; 같은 비교 연산자들은 피연산자 타입에 따라 숫자나 문자열 알파벳 순서대로 비교를 수행한다. 각 연산자의 명세를 보면 해당 연산자의 타입 종속성은 어떤지, 그리고 어떤 타입 변환이 이루어지는지 알 수 있다.</p>\n<p>4.7.3 좌변 값</p>\n<p>표 4-1 ㅔ서 할당 연산자를 비롯한 몇 가지 연산자의 피 연산자 타입은 '좌변 값(lvalue)'이다. 좌변 값이란 '할당 표현식의 좌변에 나타날 수 있는 표현식'에서 유래한 용어다. 자바스크립트에서는 변수, 객체 프로퍼티, 배열 원소가 좌변 값이다. EMCAScript 명세에 의하면 내장 함수도 좌변 값을 반환할 수 있다고 한다. 하지만 실제로 이와 같은 형태로 정의된 내장 함수는 하나도 없다.</p>\n<p>4.7.4 연산자 부수 효과</p>\n<p>2 * 3 과 같은 간단한 표현식의 평가 결과는 프로그램의 상태에 영향을 끼치지 않으며, 프로그램이 미래에 수행할 어떤 계산에도 영향을 끼치지 않는다. 하지만 일부 표현식은 부수 효과 (side effect)를 갖는다. 이러한 효과는 미래의 평가 결과에도 영향을 미치게 된다. 할당 연산자가 대표적인 경우인데, 변수나 객체의 프로퍼티에 값을 할당하면 그 변수나 프로퍼티를 사용하는 모든 표현식의 값이 바뀌는 것이다. 이와 유사하게 증가 연산자 ++와 감소 연산자 --도 실행되면 기존의 값을 변경하는 묵시적 할당이 이루어진다. delete 연산자도 부수 효과가 있는데, 프로퍼티를 삭제하는 것은 해당 프로퍼티에 undefined 값을 할당하는 것과 유사하다(하지만 똑같지는 않다).</p>\n<p>다른 자바스크립트 연산자는 부수 효과가 없다. 하지만 함수 또는 생성자 몸체에 부수 효과가 있는 연산자를 사용한다면 함수 호출 또는 객체 생성 표현식에서도 부수 효과가 나타날 수 있다.</p>\n<p>4.7.5 연산자 우선순위\n표 4-1에 나열한 연산자들은 우선순위가 가장 높은 연산자부터 우선순위가 낮은 연산자 순로 정렬되어 있다. 우선순위가 같은 산자들끼리는 선으로 구분하였다. 연산자 우선순위는 연산이 수행되는 순서를 제어하는 기준이 된다. 우선순위가 높은 연산자는 상대적으로 우선순위가 낮은 연산자보다 먼저 수행된다. 다음 표현식을 살펴보자.</p>\n<p>w = x + y*z;</p>\n<p>곱셈 연산자 *는 덧셈 연산자 +보다 우선순위가 높다. 따라서 곱셈이 덧셈보다 먼저 수행된다. 또한 할당 연산자 =는 우선순위가 가장 낮기 때문에 오른쪽의 모든 연산이 완료된 후에야 할당 연산이 수행된다.\n원래 정해진 연산자 우선순위를 바꾸려면 명시적으로 괄호를 쓰면 된다. 앞의 예에서 강제로 덧셈을 먼저 수행하려면 다음과 같이 작성하면 된다.</p>\n<p>w = ( x + y ) * z;</p>\n<p>참고로, 프로퍼티 접근이나 호출 표현식은 표 4-1에 나열된 연산자들보다 항상 우선순위가 높다. 다음 표현식을 살펴보자.</p>\n<p>typeof my.functions<a href=\"y\">x</a></p>\n<p>비록 typeof 연산자가 우선순위가 높은 연산자 중 하나지만, 프로퍼티 접근과 함수 호출이 끝난 후에야 실행된다. 실전에서 어떤 연산이 우선하는지 확신이 서지 않는다면, 가장 간단한 해결책은 괄호를 사용해 연산 순서를 명시적으로 지정하는 것이다. 단, 한 가지 알아둘 중요한 규칙은 다음과 같다. 곱셈과 나눗셈은 덧셈과 뺄셈보다 먼저 수행되며, 할당은 우선순위가 아주 낮기 때문에 대부분의 경우 마지막으로 수행된다는 점이다.</p>\n<p>4.7.6 연산자 결합 방향</p>\n<p>표 4-1에서 'A' 라고 표시된 열은 연산자 '결합 방향(associativity)'을 지정한다고 설명했다. L은 왼쪽에서 오른쪽으로의 결합 방향을, R은 오른쪽에서 왼쪽으로의 결합 방향을 나타낸다. 연산자 결합 방향이 지정하는 것은 동일 우선순위 연산들 간의 수행 순서를 의미한다. 왼쪽에서 오른쪽으로의 결합 방향은 연산이 왼쪽에서 오른쪽으로 일어난다는 의미다. 예를 들어 뺄셈 연산자는 결합 방향이 왼쪽에서 오른쪽(L)이기 때문에,</p>\n<p>w = x - y - z;</p>\n<p>이 표현식은 다음과 동일하다.</p>\n<p>w = (( x - y) - z );</p>\n<p>반면, 다음의 표현식들은,</p>\n<p>x = ~-y;\nw = x = y = z;\nq = q?b:c?d:e?f:g;</p>\n<p>다음 표현식들과 각각 동일하다.</p>\n<p>x = ~(-y);\nw = ( x = ( y = z));\nq = a?b:*c?d:(e?f:g));</p>\n<p>이렇게 되는 이유는 단항, 할당, 3항 비교 연산자들의 결합 방향이 오른쪽에서 왼쪽(R)이기 때문이다.</p>\n<p>4.7.7 평가 순위</p>\n<p>연산자 우선순위와 결합 방향은 복잡한 표현식에서 어떤 연산이 우선적으로 수행되는지를(order of evaluation) 결정한다. 하지만 어떤 부 표현식(sub-expression)이 먼저 평가되는지를 정하지는 않는다. 예를 들어 표현식 w=x+y*z의 경우, 부 표현식 w가 먼저 평가되고, x,y,z가 차례대로 평가된다. 그 후에 y와 z를 곱한 후, x 값을 더해서 표현식 w가 가리키는 변수나 객체 프로퍼티로 값을 할당한다. 표현식에 괄호를 추가하면 곱셈, 덧셈, 할당 사이의 순서를 변경할 수 있다. 하지만 왼쪽에서 오른쪽으로의 평가 순서까지 바꿀 수는 없다.</p>\n<p>평가 순서는, 표현식 가운데에 다른 표현식의 값에 영향을 끼치는 표현식이 포함된 경우에만 중요하다. 만약에 표현식 x가 z에서 사용하고 있는 임의의 변수 값을 증가시킨다고 할 때, 여기서 중요한 점은 x가 반드시 z보다 먼저 평가되어야 한다는 것이다.</p>\n<p>4.8 산술 표현식</p>\n<p>이번 절에는 피연산자들에 산술 연산이나 기타 수치 조작을 하는 연산자에 대해 다룬다. 곱셈, 나눗셈, 뺄셈 연산자는 매우 직관적이기 때문에 다른 연산자보다 먼저 다루겠다. 덧셈 연산자는 단순히 우리가 알고 있는 덧셈 연산뿐 아니라 문자열을 이어붙일 수도 있고, 피연산자의 타입을 바꿀 수도 있어서 별도의 절에서 자세히 다룰 것이다. 단항 연산자와 비트 연산자 또한 세부 절에서 살펴보겠다.</p>\n<p>기본 산술 연산자는 *(곱셈), /(나눗셈), %(나머지), +(덧셈), -(뺄셈)이다. 앞에서 언급했듯이, + 연산자는 별도의 절에서 살펴보겠다. 다른 네가지 기본 산술 연산자는 단순히 각각의 피연산자를 평가하고, 값을 숫자로 변환한다. 그 다음에 피연산자들의 최종 값으로 곱셈, 나눗셈, 나머지, 뺄셈 연산을 수행한다. 수로 변환 불가능한 피연산자는 NaN 값으로 변환되며, 피 연산자 중 하나라도 NaN일 경우에는 연산 결과도 NaN이다.</p>\n<p>/연산자는 첫 번째 피연산자를 두 번째 피연산자로 나눈다. 여러분이 정수와 부동소수점 숫자를 구분하는 프로그래밍 언어에 익숙하다면, 정수를 정수로 나누면 계산 값이 당연히 정수가 되리라고 예상할 것이다. 하지만 자바스크립트에서 모든 숫자는 부동소수점 숫자로 취급된다. 따라서 모든 나눗셈 연산의 결과 또한 부동소수점 숫자 값이 된다. 예를 들어 5.2는 2가 아니라 2.5로 평가된다. 값을 0으로 나누면 양의 무한대 또는 음의 무한대 값이 되고, 0/0의 값은 NaN로 평가된다. 이들 중 어떠한 경우라도 에러가 발생하지 않는다.</p>\n<p>% 연산자는 첫 번째 피연산자에 대한 두 번째 피연산자의 나머지 연산을 수행한다. 다시 말하면 첫 번째 피연산자를 두 번째 피연산자로 나누고 남은 나머지를 반환한다는 것이다. 결과의 부호는 첫 번째 피연산자의 부호와 동일하다. 예를 들어, 5 % 2의 결과는 1이고, -5 % 2의 결과는 -1이다.\n일반적으로 나머지 연산자는 정수 타입의 피연산자에 대해 사용되지만, 부동소수점 값에 대해서도 적용할 수 있다. 예를 들어 6.5 % 2.1 의 결과는 0.2 이다.</p>\n<p>4.8.1 덧셈 연산자 +</p>\n<ul>\n<li>연산자가 이항 연산자로 사용될 떄는 피 연산자 숫자 값을 더하거나 피연산자 문자열을 이어 붙인다.</li>\n</ul>\n<p>1 + 2 // => '3'\n\"hello\" + \" \" + \"there: // => 'hello there'\n\"1\" + \"2\" // => '12'</p>\n<p>두 피연산자 값이 모두 숫자거나 문자열인 경우에는 + 연산자가 하는 일이 명확하다. 하지만 이 외의 경우에는 타입 변환이 이루어져야 하고, 연산은 타입 변환이 이루어진 후에 수행된다. + 연산자는 타입 변환 시에 문자열 이어붙이기를 먼저 수행한다. 만일 피연산자 중 하나가 문자열이거나 문자열로 바꿀 수 있는 객체라면 다른 피연산자를 문자열로 변환한 후 두 문자열을 이어 붙인다. 덧셈은 두 피연산자 값이 모두 문자열이 아니거나 문자열로 변환될 수 없을 때만 수행된다. 기술적으로 + 연산자는 다음과 같이 동작한다.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">• 만일 하나의 피연산자 값이 객체라면, 3.8.3 에서 설명한 알고리즘을 이용해 객체를 원시 타입으로 바꾼다. Date 객체는 toString() 메서드에 의해 문자열로 바뀌고, 다른 객체들은 valueOf() 메서드가 원시 타입의 값을 반환 하는 경우 그 반환값으로 변경된다. 그러나 대부분의 객체는 이처럼 유용한 valueOf() 메서드를 가지고 있지 않으므로, 그 대신 toString() 메서드를 통해 변환된다.\n• 피연산자가 객체에서 원시 타입으로 변환된 후, 만일 어떤 피연산자라도 문자열이면, 다른 피연산자를 문자열로 변환한 후 두 문자열을 이어 붙인다.\n• 이 외의 경우에는 두 피연산자가 숫자(또는 NaN)로 변환되고 덧셈 연산이 수행된다.</code></pre></div>\n<p>몇 가지 예를 살펴보자.</p>\n<p>1 + 2 // => 3: 덧셈\n\"1\" + \"2\" // => '12': 이어붙이기\n\"1\" + 2 // => '12': 숫자를 문자열로 바꾼 후 이어붙이기\n1 + { ? } // => \"1[object Object]\" : 객체를 문자열로 바꾼 후 이어붙이기\ntrue + true // => 2: 불리언 값을 숫자로 바꾼 후 더하기\n2 + null // => 2: null 값을 0으로 바꾼 후 더하기\n2 + undefined // => NaN: undefined를 NaN으로 바꾼 후 더하기</p>\n<p>마지막으로, + 연산자는 여러 문자열과 여러 숫자를 함께 사용할 때는 연산자 결합 법칙이 적용되지 않는다는 점을 반드시 기억해야 한다. 다시 말해, 연산자가 실행된 순서에 따라 연산 결과가 달라질 수 있다는 의미다. 예를 들면, 다음과 같다.</p>\n<p>1 + 2 + \" blind mice \"; // => '3 blind mice '\n1 + ( 2 + \" blind mice\"); // => '12 blind mice'</p>\n<p>1행은 괄호가 없기 때문에 + 연산자는 왼쪽에서 오른쪽으로 결합된다. 따라서 두 숫자가 먼저 계산되고, 그 결과 값을 문자열로 바꾼 후 남은 문자열을 이어붙인다. 2행에서는 괄호가 연산의 순서를 바꾼다. 숫자 2가 문자열로 바뀌어 문자열과 하나로 합쳐진다. 그 다음에 숫자 1을 문자열로 바꾼 후 남은 문자열을 이어붙인다.</p>\n<p>4.8.2 단항 산술 연산자</p>\n<p>단항 연산자는 하나의 피연산자 값을 수정해서 새 값으로 만든다. 자바스크립트에서는 단항 연산자가 가장 우선순위가 높고, 결합 방향은 모두 오른쪽에서 왼쪽이다. 이번 절에서 설명하는 산술 단항 연산자 (+, -, ++, --)는 하나의 피연산자를 가능한 한 숫자 타입으로 변환하려 시도한다. 느낌표(!) 문자와 +, =는 단항과 이항 연산자 양쪽으로 사용할 수 있다. 단항 산술 연산자는 다음과 같다.</p>\n<p>단항 덧셈(+)</p>\n<p>단항 덧셈 연산자는 피연산자를 숫자(또는 NaN)로 바꾼 후 값을 반환한다. 만일 피연산자가 숫자인 경우에는 아무 일도 하지 않는다.</p>\n<p>단항 뺄셈(-)</p>\n<p>뺄셈 연산자가 단항 연산자로 사용될 때는, 피연산자를 가능하면 숫자로 변환하려고 시도하고, 성공할 경우에 결과 값의 부호를 바꾼다.</p>\n<p>증가(++)</p>\n<p>++ 연산자는 단항 피연산자에 대해 증가 연산을 한다(즉, 1을 더한다). 이떄 피연산자는 반드시 좌변 값(변수, 배열 원소 또는 객체 프로퍼티 중 하나)이어야 한다. 이러한 변수, 원소, 프로퍼티가 숫자가 아닐 경우 ++ 연산자는 일단 이를 숫자 타입으로 변환하고, 거기 1을 더한 다음, 원래 변수나 원소, 프로퍼티에 대입한다.</p>\n<p>이 연산자의 결과 값은 피연산자의 어느쪽에 연산자가 위치해 있는지에 따라 다르다. 피연산자의 앞에서 사용될 경우에는 전치증가(pre-increment) 연산자라고 하며, 먼저 피연산자를 증가시킨 다음 증가된 값을 결과로 내놓는다. 피연산자의 뒤에서 사용될 경우 후치증가(post-increment) 연산자라고 하며, 마찬가지로 피연산자를 증가시키지만 결과로는 원래의 증가되지 않은 값을 내놓는다.\n다음 두 코드 사이의 차이점을 살펴보자.</p>\n<p>var i = 1, j = ++i; // i와 j 모두 2이다.\nvar i = 1, j = i++; // i는 2이고, j는 1이다.</p>\n<p>표현식 ++x는 x=x+1과 항상 같지 않음을 명심하자. ++ 연산자는 절대 문자열 결합 연산을 하지 않고, 항상 피연산자를 숫자로 바꾼 후에 값을 하나 증가시킨다. 예를 들어, x가 문자열 \"1\"이면 ++x는 숫자 2가 되지만 x+1은 문자열\"11\"이 된다.</p>\n<p>자바스크립트에서는 자동 세미콜론 삽입 기능이 있기 떄문에, 후치증가 연산자와 그 앞에 있는 피연산자 사이에서 줄바꿈을 해서는 안 된다. 만일 이럴 경우 자바스크립트에서 이 피연산자 자체를 하나의 표현식으로 취급하게 되어 연산자 앞에 세미콜론을 삽입할 것이다. 이 연산자는 전치 및 후치 형태로 사용할 수 있고, 일반적으로 for 루프의 제어 카운터를 증가시키는 데 많이 쓰인다(5.5.3 참고).</p>\n<p>감소(--)</p>\n<p>-- 연산자 역시 ++ 연산자와 마찬가지로 좌변 값(변수, 배열 원소 또는 객체 프로퍼티 중 하나)을 피연산자로 갖는다. -- 연산자는 단항 피연산자의 값을 숫자로 바꾼 후에 1을 뺀다. 그 다음에 감소한 값을 피연산자에 다시 할당한다. ++ 연산자와 마찬가지로 -- 연산자 역시, 연산자가 어느 쪽에 위치해 있는지에 따라 결과 값이 달라진다. 만약 피연산자 앞에 있으면 피연산자의 값을 감소시키고, 감소시킨 값을 반환한다. 만일 피연산자 뒤에 있으면, 피연산자의 값을 감소시키지만 감소시키기 전 값을 반환한다. ++ 연산자에서와 같은 이유로 연산자가 후치 감소 연산자로 사용될 때는 연산자와 피연산자 사이에 줄바꿈이 있어서는 안 된다.</p>\n<p>4.8.3 비트 단위 연산자</p>\n<p>비트 단위 연산자들은 2진수를 저수준에서 조작하는 데 사용한다. 사칙연산과 같은 산술 연산을 수행하지는 않지만, 피연산자로 숫자 값을 사용하고 최종적으로 숫자 값을 반환하기 때문에 자바스크립트에서는 산술 연산자로 분류되어 있다. 이러한 연산자는 자바스크립트에서 일반적으로 널리 쓰이지 않는다. 만일 여러분이 10진수 정수를 2진수로 표현하는 것에 익숙하지 않다면 이번 절에서 설명하는 연산자들을 건너뛰어도 좋다. 비트 단위 연산자 중 네 종류(&#x26;, |, ^, ~)는 피연산자의 개별 비트에 대해 불리언 대수(Boolean Algebra)를 수행한다. 이때 피연산자의 개별 비트는 불리언 값으로 취급된다( 1 = true, 0 = false). 다른 세 종류의 비트 단위 연산자(&#x3C;&#x3C;, >>, >>>)는 왼쪽이나 오른쪽으로 비트를 이동할 때 사용된다.</p>\n<p>비트 단위 연산자의 피연산자로는 정수가 온다. 여기서 정수는 64비트 부동 소수점 표현법이 아니라 32비트 정수 표현법을 따른다. 비트 단위 연산자는 피연산자의 값을 가능하면 숫자로 바꾸고, 32번째 이후 비트를 잘라내어 강제로 피연산자 값을 32비트로 만든다. 이동 연산자(shift operator)의 우측 피연산자는 0과 31 사이의 값이어야 한다. 이동 연산자는 피연산자를 32비트 정수로 변환한후 여섯 번째 이상의 비트를 버림으로써 이 숫자가 적절한 범위에 들도록 한다. 놀랍게도 NaN, 양의 무한대(infinity), 음의 무한대(-infinity)는 비트 단위 연산자의 피연산자로 사용될 떄 모두 값이 0으로 바뀐다.</p>\n<p>비트 단위 AND(&#x26;)</p>\n<p>&#x26; 연산자는 두 정수 피연산자의 개별 비트끼리 불리언 AND 연산을 수행한다. 동일 위치의 비트가 두 피연산자에서 모두 설정되어 있어야만 결과 값의 해당 비트도 설정된다. 예를 들어 0x1234 &#x26; 0x00FF의 결과는 0x0034다.</p>\n<p>비트 단위 OR ( | )</p>\n<p>| 연산자는 두정수 피연산자의 개별 비트끼리 불리언OR 연산을 수행한다. 적어도 하나 이상의 피연산자에게 특정 위치의 비트가 설정되어 있으면 결과 값의 해당 위치 비트가 설정된다. 예를 들어 0x1234 | 0x00FF의 결과는 0x12FF다.</p>\n<p>비트 단위 XOR (^)</p>\n<p>^연산자는 두 정수 피연산자의 개별 비트끼리 배타적(exclusive) 불리언 OR (XOR) 연산을 수행한다. 배타적 OR란 두 연산자 중 하나가 true이지만 둘 다 true는 아닐때 결과가 true가 된다. 두 피연산자 중 하나에만 특정 위치의 비트가 설정되어 있으면 결과 값의 해당 위치 비트도 설정된다. 예를 들어 0xFF00 ^ 0xF0F0의 결과는 0x0FF0다.</p>\n<p>비트 단위 NOT (~)</p>\n<p>~연산자는 단항 연산자로 하나의 정수 피연산자 앞에 위치한다. ~ 연산자는 피연산자의 모든 비트를 반전시킨다. 자바스크립트에서 부호 있는 정수를 표현하는 방법으로 인해, 어떤 값에 ~ 연산자를 적용하면 그 값의 부호를 바꾸고 1을 빼는 것과 같은 결과를 얻게 된다. 예를 들어 ~0x0F는 0xFFFFFFF0이며, 이는 -16과 같다.</p>\n<p>왼쪽으로 이동 (&#x3C;&#x3C;)</p>\n<p>&#x3C;&#x3C; 연산자는 첫 번째 피연산자의 모든 비트를 두 번째 피연산자에서 지정한 자릿수만큼 왼쪽으로 이동시킨다. 두 번째 피연산자는 반드시 0과 31 사이의 정수여야 한다. 예를 들어 a &#x3C;&#x3C; 1 연산의 경우 a의 첫 번째 비트는 두 번째 비트가 되고, 두 번째 비트는 세 번째 비트가 되고… 이 과정이 이어진다. 모든 비트를 이동시키면 첫 번째 비트를 새 만들어야 하는데, 새로 만들어지는 비트의 값으로는 0이 사용되며 기존의 32번째 비트는 잃어버리게 된다. 어떤 값을 왼쪽으로 한 자리 이동시키는 것은 2를 곱하는 것과 같으며, 두 자리 이동시키는 것은 4를 곱하는 것과 같다. 예를 들어 7 &#x3C;&#x3C; 2의 결과는 28이다.</p>\n<p>부호를 보존하면서 오른쪽으로 이동 ( >>)</p>\n<blockquote>\n<blockquote>\n<p>연산자는 첫 번째 피연산자의 모든 비트를 두 번째 피연산자에서 지정한 자릿수만큼 오른쪽으로 이동시킨다. 두 번째 피연산자는 반드시 0과 31 사이의 정수여야 한다. 비트를 오른쪽으로 이동시키면 맨 오른쪽 비트들은 손실된다. 왼쪽 자리에 채워질 비트는 최소 피연산자의 부호 비트가 되고, 이는 곧 결과 값의 부호가 된다. 첫 번째 피연산자가 양수면, 결과 값의 최상위 비트가 0이 되고, 음수면 최상위 비트 1이 된다. 어떤 값을 오른쪽으로 한 자리 이동시키는 것은 이 값을 2로 나누는 것과 같고, 오른쪽으로 두 자리를 이동시키는 것은 값을 4로 나누는 것과 같다. 예를 들어, 7 >> 1의 결과는 3이고, -7 >> 1의 결과는 -4다.</p>\n</blockquote>\n</blockquote>\n<p>0으로 채우면서 오른쪽으로 이동 ( >>> )</p>\n<blockquote>\n<blockquote>\n<blockquote>\n<p>연산자는 >> 연산자와 한 가지를 제외하고는 똑같다. 차이점은, 왼쪽 자리에 새로 들어오는 비트가 첫 번째 피연산자의 부호에 관계없이 무조건 0이라는 점이다. 예를 들어, -1 >> 4의 결과는 -1이지만, -1 >>> 4의 결과는 0x0FFFFFFF다.</p>\n</blockquote>\n</blockquote>\n</blockquote>\n<p>4.9 관계형 표현식</p>\n<p>이번 절에서는 자바스크립트에서 사용하는 관계형 연산자(relational operator)를 다룬다. 이러한 연산자들은 두 피연산자 값의 관계(이를테면 두 값이 같은지, 한 값이 다른 값보다 작은지 또는 한 값이 다른 값의 프로퍼티로 존재하는지 등)를 검사하여, 관계가 성립하면 true를, 그렇지 않으면 false를 반환한다. 관계형 표현식은 항상 불리언 값으로 평가되고, 이 값은 프로그램 실행의 흐름을 제어하기 위한 if문, while문, for 루프문에서 주로 사용된다. 이제부터 동치와 부등치 연산자, 비교 연산자, 관계형 연산자인 in과 instanceof를 살펴보겠다.</p>\n<p>4.9.1 동치와 부등치 연산자</p>\n<p>==와 === 연산자 모두 주어진 두 값이 같은지를 확인하는 데 쓰이지만 같음을 정의하는 기준이 서로 다르다. 두 연산자 모두 피연산자 타입을 가리지 않고, 주어진 피연산자들이 같으면 true를, 다르면 false를 반환한다. === 연산자는 일치(엄격한 동치) 연산자로 알려져 있는데, 같음을 정의하는 기준을 매우 엄격하게 정의하여, 두 피연산자가 '일치(identical)'하는지 확인한다. == 연산자는 동치 연산자로 알려져 있으며, 두 피연산자가 '동등(equal)'한지 확인할 때 필요한 경우 타입 변환을 허용한다. 이때 같음을 정의하는 기준이 === 연산자만큼 엄격하지는 않다.</p>\n<p>자바스크립트는 =(할당), ==(동치), ===(일치) 연산자를 지원하고 있다. 여러분은 할당, 동치, 일치 연산자의 차이를 확실하게 이해해야 하며, 코딩할 때 올바른 것을 사용하도록 주의해야 한다! 이 세가지를 모두 같은(equal)연산자로 혼동하기 쉬운데, 다음과 같은 방법을 사용하면 혼동을 줄이는 데 도움이 될 것이다.\n= 연산자는 '취하다(get) 또는 할당하다(assigned)'로, == 연산자는 '~와 같은 값으로 볼 수 있다(is equal to)', 마지막으로 === 연산자는 '~와 일치한다(is strictly equal to)'로 읽는 것이다.\n!=와 !== 연산자가 비교하는 것은 앞에서 살펴본 ==와 ===연산자가 비교하는것과 정확히 반대다. 부등치 연산자 !=는 두 값이 서로 동치일 경우 false를 반환하며, 그렇지 않을 경우 true를 반환한다. 불일치 연산자 !==는 두 값이 서로 일치할 경우 false를 반환하며, 그렇지 않을 경우 true를 반환한다. 4.10절에서 살펴보겠지만, ! 연산자는 불리언 NOT 연산을 수행한다. 이 점을 감안하면 !=가 '같은 값으로 볼 수 없다'를 나타내며, !==는 '일치하지 않는다'를 말한다는 사실을 쉽게 떠올릴 수 있을 것이다.</p>\n<p>3.7절에서 설명했듯이, 자바스크립트는 값 비교가 아닌, 참조 비교를 수행한다. 간단히 말해서, 객체는 자기 자신과는 같지만 다른 객체와는 같지 않다. 예를 들어 두 개의 서로 다른 객체가 같은 수의 프로퍼티를 갖고, 각 프로퍼티 이름과 값이 서로 같더라도 두 객체는 여전히 다른 객체다. 마찬가지로 두 배열이 같은 원소들을 같은 순서로 가지고 있을지라도, 이 두 배열은 같지 않다.\n일치 연산자 ===가 두 값이 일치하는지 여부를 판단할 때는 다음의 규칙을 따르며, 타입 변환은 하지 않는다.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">• 두 값의 타입이 서로 다르면 두 값은 일치하지 않는다.\n• 두 값이 모두 null이거나 모두 undefined면, 두 값은 일치한다.\n• 두 값이 모두 불리언 값 true이거나 모두 false일 경우에, 두 값은 일치한다.\n• 적어도 하나의 값이 NaN이면 두 값은 일치하지 않는다. NaN값은 자기 자신을 포함해 다른 어떠한 값과도 일치하지 않는다. 임의의 값 x가 NaN인지 검사하기 위해서는 x !== x와 같이 사용하면 된다. NaN은 이 표현식을 참으로 만드는 유일한 값이다.\n• 두 값이 모두 숫자고 같은 값을 갖는다면, 두 값은 일치한다. 만약 하나의 값이 0이고 다른 하나의 값이 -0일지라도, 두 값은 일치한다.\n• 두 값이 모두 문자열이고, 같은 위치에 정확히 같은 16비트 값(3.2절 참고)을 가지고 있다면, 두 값은 일치한다. 만약 문자열의 길이나 내용이 다를 경우, 두 값은 일치하지 않는다. 두 문자열이 같은 의미를 갖고, 육안상 같은 문자열을 갖더라도 16비트 값의 순서가 다르게 인코딩되어 있을 수도 있다. 자바스크립트에서는 유니코드 문자열에 대해서 정규화 과정을 수행하지 않으며, 이런 문자열들은 === 나 == 연산자로는 같다고 판정되지 않는다. 이와 같은 문자열을 비교하려면 3부에서 다루는 String.localeCompare()를 참고하라.\n• 두 값이 모두 같은 객체나 배열 또는 함수를 참조하고 있으면, 두 값은 일치한다. 두 값이 서로 다른 객체를 참조할 경우에 ㅅ ㅓㄹ사 두 객체의 프로퍼티가 일치하더라도 두 값은 일치하지 않는다.</code></pre></div>\n<p>동치 연산자 ==는 일치 연산자와 유사하지만 상대적으로 규칙이 엄격하지 않다. 두 피연산자의 값이 같은 타입이 아닐 경우에는 일부 피연산자에 대해 타입 변환을 시도한 후에 비교를 다시 하게 된다. 두 값이 동등한지 여부를 판단할 때는 다음의 규칙을 따른다.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">• 두 값의 타입이 같은 경우, 두 값이 일치하는지 테스트한다. 만약 두 값이 일치할 경우 두 값은 동치다. 하지만 두 값이 일치하지 않으면 두 값은 동치가 아니다.\n• 두 값의 타입이 다를 경우라 할지라도 동치일 여지가 있다. 동치임을 확인하는 과정에서 다음에 나열된 규칙들과 타입 변환이 사용된다.\n  * 두 값 중 하나가 null이고 다른 하나가 undefined라면 두 값은동등하다.\n  * 한 값이 숫자이고 다른 하나가 문자열이면, 문자열을 숫자로 변환한 후 이를 사용해 다시 비교한다.\n  * 두 값 중 하나가 true이면 이를 1로 변환한 후 다시 비교한다. 두 값 중 하나가 false이면, 이를 0으로\n    변환한 후 다시 비교한다.\n  * 한 값이 객체고, 다른 하나는 숫자 또는 문자열이면, 객체를 원시 타입의 값으로 변환한 후 다시 비교\n    한다. 객체를 원시 값으로 변환하는 데에는 해당 객체의 toString() 메서드나 valueOf() 메서드가 사용\n    된다. 코어 자바스크립트의 내장 클래스에서는 toString90 메서드를 사용하기 전에 valueOf() 메서드\n    를 사용한 변환을 먼저 시도한다. 단, Date 클래스는 예외적으로 toString() 변환을 바로 수행한다. 코\n    어 자바스크립트에 속하지 않은 객체에서는 각 구현에서 정의한 방식으로 원시 값 변환을 수행한다.\n  * 앞에서 열거하지 않은 기타 값들의 조합은 동치가 아니다.</code></pre></div>\n<p>동등함을 테스트하는 예로 다음의 비교식을 살펴보자.</p>\n<p>\"1\" == true</p>\n<p>이 표현식은 true가 된다. 겉보기에 매우 다른 값들임에도 불구하고 사실은 동등한 관계인 것이다. 이 표현식에서는 먼저 불리언 값 true가 숫자 1로 변환된후 다시 비교한다. 이어서 문자열\"1\"이 숫자 1로 변환된다. 이제 두 숫자는 같은 숫자이기 때문에 비교식의 결과로 true를 반환한다.</p>\n<p>4.9.2 비교 연산자</p>\n<p>비교 연산자는 두 피연산자 값의 상대적인 순서를 판단하는 데 쓰인다.</p>\n<p>더 작다 (&#x3C;)</p>\n<p>&#x3C; 연산자는 첫 번째 피연산자가 두 번째 피연산자보다 크면 true로, 그렇지 않으면 false로 평가된다.</p>\n<p>더 크다 (>)</p>\n<blockquote>\n<p>연산자는 첫 번째 피연산자가 두번째 피연산자보다 크면 true로, 그렇지 않으면 false로 평가된다.</p>\n</blockquote>\n<p>작거나 같다 ( &#x3C;= )</p>\n<p>&#x3C;= 연산자는 첫 번째 피연산자가 두 번째 피연산자보다 작거나 같으면 true로, 그렇지 않으면 false로 평가된<br>\n다.</p>\n<p>크거나 같다 ( >= )</p>\n<blockquote>\n<p>= 연산자는 첫 번째 피연산자가 두 번째 피연산자보다 크거나 같으면 true로, 그렇지 않으면 false로 평가된</p>\n</blockquote>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\"> 다.</code></pre></div>\n<p>비교 연산자는 피연산자 타입에 제한이 없다. 하지만 오직 숫자와 문자열만 비교할 수 있기 때문에, 숫자나 문자열이 아닌 피연산자는 먼저 변환된다. 비교와 변환은 다음과 같이 일어난다.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">• 피연산자 중 어느 하나가 객체로 평가되면, 3.8.3에서 살펴봤듯이 해당 객체가 원시 값으로 변환되는데, 이 과정에서 valueOf() 메서드의 반환값이 원시 타입이면 그 값을 이용하고, 그렇지 않은 경우에는 toString() 메서드의 반환 값을 이용한다.\n• 객체가 원시 타입으로 변환된 후에 피연산자가 모두 문자열이라면 &#39;알파벳 순서&#39;대로 두 문자열을 비교하게 된다. 여기서 &#39;알파벳 순서&#39;란 문자열을 구성하는 16비트 유니코드 값의 순서를 말한다.\n• 객체가 원시 타입으로 변환된 후에 최소한 피연산자 중 하나가 문자열이 아니면, 피연산자 모두 숫자로 변환된 후 값을 비교하게 된다. 0과 -0은 의미상 동일하다. 양의 무한대는 양의 무한대가 아닌 어떤 수보다 크고, 음의 무한대는 음의 무한대가 아닌 어떤 수보다 작다. 둘 중의 하나의 피연산자가 NaN이거나 NaN으로 변환된다면 비교 연산자는 언제나 false를 반환한다.</code></pre></div>\n<p>자바스크립트 문자열은 16비트 정수 값들의 나열이고, 문자열 비교는 단순히 두 문자열이 가지고 있는 각 문자에 해당하는 숫자 값의 비교라는 점을 유념해야 한다. 유니코드에 의해 정의된 숫자 인코딩 순서는 어떤 특정 언어나 로케일(locale)에 사용되는 고유 문자의 조합과 순서가 다를 수 있다. 또한, 문자열 비교는 대소문자를 구분한다는 점을 염두에 두어야 하는데, 모든 ASCII 대문자는 모든 ASCII 소문자보다 '작다'. 이 점을 미리 알지 못하면 문자열 비교 결과에 혼란을 겪을 수 있다. 예를 들면 &#x3C; 연산자에 대해 문자열 \"Zoo\"는 문자열 \"aardvark\"보다 작다.</p>\n<p>로케일 차이에서 오는 알파벳 순서 차이 등의 문제까지 고려하는, 좀 더 견고한 문자열 비교 알고리즘으로 String.localeCompare() 메서드가 있다. 대소문자를 구분하지 않고 문자열을 비교하려면, 우선 String.toLowerCase()나 String.toUpperCase() 메서드를 사용해서 비교할 문자열을 전부 소문자나 대문자로 변환해야 한다.</p>\n<ul>\n<li>연산자와 비교 연산자는 피연산자로 숫자가 올 경우와 문자열이 올 경우 전혀 다르게 동작한다. + 연산자는 문자열을 선호하는데, 피연산자가 문자열일 때는 문자열을 이어붙이는 방식으로 동작한다. 비교 연산자는 숫자를 선호하고, 두 피연산자들이 문자열일 때만 문자열 비교를 한다.</li>\n</ul>\n<p>1 + 2 // 덧셈. 결과는 3\n\"1\" + \"2\" // 결과는 '12'\n\"1\" + 2 // 2가 문자열로 변환되고, 결과는 '12'\n11 &#x3C; 3 // 숫자 비교. 결과는 false\n\"11\" &#x3C; \"3\" // 숫자 비교. '11'이 숫자 11로 변환되고, 결과는 false.\n\"11\" &#x3C; 3 // 숫자 비교. 결과는 false\n\"one\" &#x3C; 3 // 숫자 비교. 'one'이 NaN으로 변환되고, 결과는 false.</p>\n<p>마지막으로, &#x3C;= 연산자(더 작거나 같다)와 >= 연산자( 더 크거나 같다)는 두 값이 같은지 판단할 떄, 동치 연산자의 힘을 빌리지 않는다. 그 대신, '더 작거나 같다' 연산자는 단순히 '크지 않다'로 정의되며, '더 크거나 같다' 연산자는 단순히 '작지 않다'로 정의된다. 단 한 가지 예외가 있는데, 두 피연산자 중 하나가 NaN이면 (또는 NaN으로 변환되면) 네 종류의 비교 연산자 모두 false를 반환한다.</p>\n<p>4.9.3 in 연산자</p>\n<p>in 연산자는 좌변의 피연산자로 문자열(또는 문자열로 변환될 수 있는 것)을 받는다. 우변의 피연산자로는 객체나 배열을 받는다. 좌변 값이 우변 객체의 프로퍼티 이름에 해당할 경우 연산 결과는 true다. 예를 들어보자.</p>\n<p>var point = { x : 1, y : 1 } ; // 객체 정의\n\"x\" in point // => true: 프로퍼티 x가 있다.\n\"z\" in point // => false: 프로퍼티 z가 없다.\n\"toString\" in point // => true: 상속된 프로퍼티\nvar data = [7,8,9]; // 원소가 0, 1, 2 위치에 차례로 7, 8, 9\n\"0\" in data // => true: 배열에 0번째 원소가 있기 때문\n1 in data // => true: 배열에 1번째 원소가 있기 때문\n3 in data // => false: 배열에 3번째 원소가 없기 때문</p>\n<p>4.9.4 instanceof 연산자</p>\n<p>instanceof 연산자는 좌변의 피연산자로 객체를, 우변의 피연산자로 객체 클래스의 이름을 식별자로 받는다. 좌변에 오는 객체가 우변 클래스의 인스턴스일 경우 연산 결과는 true로 평가되고, 그렇지 않은 경우에는 false로 평가된다. 9장에서 설명하겠지만, 자바스크립트에서 객체의 클래스는 객체를 초기화하는 생성자 함수로부터 정의된다. 그러므로 instanceof의 우변 피연산자는 함수가 되어야 한다. 다음 예제를 살펴보자.</p>\n<p>var d = new Date(); // Date() 생성자로 새로운 객체를 생성한다.\nd instanceof Date; // => true: d는 Date()에 의해 생성되었다.\nd instanceof Object; // => true: 모든 객체는 Object의 인스턴스.\nd instanceof Number; // => false: d는 Number의 객체가 아니다.\nvar a = [1, 2, 3]; // 배열 리터럴 문법으로 새로운 배열을 생성한다.\nd instanceof Array; // => true: a는 배열이다.\nd instanceof Object; // => true: 모든 배열은 객체다.\nd instanceof RegExp; // => false: 배열은 정규 표현식이 아니다.</p>\n<p>모든 객체는 Object의 인스턴스라는 점을 기억하자. instanceof로 객체가 클래스의 인스턴스인지 판단할 때는 해당 객체의 '상위 클래스'들도 고려하게 된다. 만일 instanceof 의 좌변 피연산자가 객체가 아니면, instanceof 의 결과는 false다. 또한 우변 피연산자가 함수가 아니라면 TypeError 예외가 발생한다.</p>\n<p>instanceof 연산자가 어떻게 동작하는지 이해하기 위해서는 '프로토타입 체인'을 이해해야 한다. 프로토타입 체인은 자바스크립트의 상속 메커니즘으로 6.2.2에서 상세히 다룬다. o instanceof f 표현식을 평가하기 위해서 자바스크립트는 f.prototype을 평가한 후, o의 프로토타입 체인에 그 값이 나타나는지 검색한다. 만일 o의 프로토타입 체인에서 f.prototype 값이 발견되면 o는 f의 인스턴스(또는 f의 하위 클래스의 인스턴스)가 되고, 표현식은 true를 반환한다. 만일 o의 프로토타입 체인에서 f.prototype 값을 찾을 수 없으면 o는 f의 인스턴스가 아니고, 표현식은 false를 반환한다.</p>\n<p>4.10 논리 표현식</p>\n<p>논리 연산자 &#x26;&#x26;, ||, ! 은 불리언 대수(Boolean algebra)를 수행한다. 논리 연산자는 종종 비교 연산자와 함께 사용되어 둘 이상의 변수가 관계되는 복잡한 표현식을 표현하기도 한다. 각 논리 연산자는 세부 항목에서 살펴볼 것이다. 논리 연산자를 온전히 이해하기 위해서는 3.3절에서 설명한 '참이 되는(truthy) 표현식' 과 '거짓이 되는(falsy) 표현식'의 개념을 다시 한번 살펴볼 필요가 있다.</p>\n<p>4.10.1 논리 AND ( &#x26;&#x26; )</p>\n<p>&#x26;&#x26; 연산자는 크게 세 가지 수준에서 이해할 수 있다. 첫 번째 수준은 아주 단순한 것으로, 연산자가 불리언 피연산자에 대해 쓰일 경우에는 두 피연산자의 값에 대한 불리언 AND를 수행한다. 첫 번째 피연산자와 두 번째 피연산자가 '모두' true일 경우에만 연산 결과로 true를 반환한다. 적어도 하나 이상의 피연산자가 false라면 연산 결과로 false를 반환한다. &#x26;&#x26; 는 종종 두 관계 표현식의 접속사 (conjunction)로도 쓰인다.</p>\n<p>x == 0 &#x26;&#x26; y == 0 // x와 y가 모두 0이면 참이 된다.</p>\n<p>관계 표현식은 항상 true나 false로 평가되기 때문에, 위와 같이 &#x26;&#x26;를 사용하면 항상 true나 false를 반환하게 된다. 관계 연산자는 &#x26;&#x26; 와 || 보다 연산자 우선순위가 높기 떄문에, 위와 같은 표현식은 괄호 없이도 안전하게 사용할 수 있다. 하지만 &#x26;&#x26; 연산자의 피연산자로 반드시 불리언 값이 올 필요는 없다. 모든 자바스크립트 값은 true로 평가될 수 있거나(truthy) false로 평가될 수 있음(falsy)을 상기하자(3.3절에서 자세히 다루고있다. false로 평가되는 값은 false, null, undefined, 0, -0, NaN, ''(빈문자열)이다. 객체를 비롯한 이 외의 다른 모든 값은 true로 평가된다).</p>\n<p>&#x26;&#x26; 연산자를 이해하는 두 번째 방법은 true나 false로 평가되는 값들을 위한 불리언 AND 연산자로써 이해하는 것이다. 피연산자 모두 true로 평가되는 값이면, &#x26;&#x26; 연산자는 true로 평가되는 값을 반환한다. 하지만 적어도 하나의 피연산자가 false로 평가될 경우에는 false로 평가되는 값을 반환한다. 자바스크립트에서 불리언 값을 요구하는 표현식이나 구문은 'truthy'한 값이나 'falsy'한 값과도 잘 동작한다. 이러한 이유로 &#x26;&#x26;가 항상 true나 false를 반환 하진 않는다는 사실이 실질적인 문제를 일으키지는 않는다.</p>\n<p>지금까지 &#x26;&#x26; 연산자가 'true로 평가되는 값' 또는 'false로 평가되는 값'을 반환한다고 했는데 정확히 어떤 값을 말하는지 설명하지 않았다. 그래서 &#x26;&#x26; 연산자를 이해하는 세 번째 수준의 방법을 설명해야 한다. &#x26;&#x26; 연산자는 좌변에 있는 첫 번째 피연산자인 표현식을 먼저 평가한다. 좌변의 값이 'falsy'면, 전체 표현식의 값 역시 'falsy'여야 하므로, 단순히 좌변의 'falsy'값을 반환하고 우변의 표현식은 평가하지 않는다.</p>\n<p>반대로, 만약 좌변의 값이 'truthy'면 전체 표현식의 값은 우변 값에 따라 달라진다. 우변의 값이 'truthy'면 전체 표현식의 값도 'truthy'고, 만약 우변의 값이 'falsy'면 전체 표현식의 값도 'falsy'다. 그렇기 때문에 좌변의 값이 'truthy'면 &#x26;&#x26; 연산자는 항상 우변의 값을 평가하고 반환한다.</p>\n<p>var o = { x : 1 };\nvar p = null;\no &#x26;&#x26; o.x // => 1: o가 객체이기 때문에 o.x를 반환한다.\np &#x26;&#x26; p.x // => null: p가 null이기 때문에 p.x를 평가하지 않고 null을 반환</p>\n<p>여기서 &#x26;&#x26;가 우변 표현식을 평가할 수도, 또는 하지 않을 수도 있다는 점을 이해해야만 한다. 이 코드에서 변수 p는 null이기 때문에 표현식 p.x가 평가되면 TypeError가 발생한다. 하지만 실제로는 &#x26;&#x26; 연산자는 p를 먼저 평가하기 때문에, 표현식 p.x는 반드시 p가 true로 평가될 때만(값이 null이나 undefined가 아닐 때) 실행된다. 이와 같은 &#x26;&#x26; 연산자의 특성을 '단축 평가(short circuiting)'라고 부르고, 이와 같은 특성을 일부러 사용하는 코드를 종종 보게 된다. 예를 들면 다음 두 줄의 자바스크립트 코드는 동일하게 작동한다.</p>\n<p>if ( a == b) stop(); // a == b를 만족할 때만 stop() 함수를 호출한다.\n( a == b ) &#x26;&#x26; stop(); // 작동은 위와 같다.</p>\n<p>일반적으로 &#x26;&#x26; 우변에 부수 효과가 일어나는 표현식(할당, 증가, 감소, 함수 호출)을 사용할 때는 각별히 주의해야 한다. 이러한 부수 효과가 일어나는 표현식은 &#x26;&#x26; 좌변 값에 따라 실행 여부가 결정된다.\n이 연산자는 실제 작동이 꽤나 혼란스러운 방식임에도 불구하고, 가장 일반적으로 사용되는 단순한 불리언 대수 연산자다.</p>\n<p>4.10.2 논리 OT ( || )</p>","excerpt":"표현식 (expression)은 자바스크립트 인터프리터가 값으로 평가하는(evaluate) 자바스크립트 구문이다. 예를 들어 프로그램에 포함된 임의의 상수는 표현식의 아주 간단한 형태다. 변수 이름 또한 간단한 표현식으로, 변수에 할당된 임의의 값으…","tableOfContents":"","fields":{"slug":"/javascript-study_3/"},"frontmatter":{"title":"javascript 표현식과 연산자","date":"Oct 27, 2021","tags":["javascript"],"keywords":["Dev.seungwon Jang","seungwon Jang"],"update":"Oct 27, 2021"}}},"pageContext":{"slug":"/javascript-study_3/","series":[{"slug":"/javascript-study_1/","title":"javascript 어휘구조","num":1},{"slug":"/javascript-study_2/","title":"javascript 타입 값 변수","num":2},{"slug":"/javascript-study_3/","title":"javascript 표현식과 연산자","num":3}],"lastmod":"2021-10-27"}},"staticQueryHashes":["2027115977","694178885"]}